package com.yyfax.pay.order.model.vo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Ordering;
import com.yyfax.commons.lang.DateUtil;
import com.yyfax.framework.yyfax.enums.YesNoEnum;
import com.yyfax.pay.common.enums.PayRspCodeEnum;
import com.yyfax.pay.common.enums.PayStepEnum;
import com.yyfax.pay.order.model.po.PayOrderExtPO;
import com.yyfax.pay.order.model.po.PayOrderLogPO;
import com.yyfax.pay.order.model.po.PayOrderPO;

/**
 * 支付订单快照信息
 * 
 * @author buyi
 * @date 2017-04-16 11:42:11
 * @since v1.0.0
 */
@SuppressWarnings("serial")
public class PayOrderVO extends PayOrderPO {
	private PayOrderExtPO payOrderExtPO;

	private List<PayOrderLogPO> orderLogPOs;

	public PayOrderVO() {
		super();
		// 初始化日志集合
		this.orderLogPOs = new ArrayList<>();
	}

	public PayOrderVO(PayOrderPO payOrderPO, PayOrderExtPO orderExtPO) {
		BeanUtils.copyProperties(payOrderPO, this);
		this.setPayOrderExtPO(orderExtPO);
	}

	public PayOrderExtPO getPayOrderExtPO() {
		return payOrderExtPO;
	}

	public void setPayOrderExtPO(PayOrderExtPO payOrderExtPO) {
		this.payOrderExtPO = payOrderExtPO;
	}

	public List<PayOrderLogPO> getOrderLogPOs() {
		return orderLogPOs;
	}

	public void setOrderLogPOs(List<PayOrderLogPO> orderLogPOs) {
		if (orderLogPOs == null) {
			return;
		}

		this.orderLogPOs = orderLogPOs;
	}

	/**
	 * 新增日志
	 * 
	 * @author buyi
	 * @date 2017-05-02 10:48:00
	 * @since v1.0.0
	 * @param orderLogPO
	 * @return
	 */
	public boolean addOrderLogPO(PayOrderLogPO orderLogPO) {
		return this.orderLogPOs.add(orderLogPO);
	}

	/**
	 * 判断订单是否关闭
	 * 
	 * @author buyi
	 * @date 2017-05-02 10:35:04
	 * @since v1.0.0
	 * @return
	 */
	public boolean isClose() {
		if (this.orderLogPOs == null || this.orderLogPOs.isEmpty()) {
			return false;
		}

		for (PayOrderLogPO orderLogPO : this.orderLogPOs) {
			if (YesNoEnum.YES.isValue(orderLogPO.getClosed())) {// 设置订单关闭状态
				return true;
			}
		}

		return false;
	}

	/**
	 * 判断订单是否失效
	 * 
	 * @author buyi
	 * @date 2017-05-02 10:37:05
	 * @since v1.0.0
	 * @return 如果失效，返回true；反之返回false;
	 */
	public boolean isExpire() {
		if (StringUtils.isBlank(this.getExpireTime())) {
			return false;
		}

		// 判断订单是否失效
		if (DateUtil.str2DateTime(this.getExpireTime()).getTime() <= System.currentTimeMillis()) {
			return true;
		}

		return false;
	}

	/**
	 * 获取订单流水号
	 * 
	 * @author buyi
	 * @date 2017-05-02 10:39:33
	 * @since v1.0.0
	 * @return
	 */
	public String getSerialNo() {
		if (this.orderLogPOs == null || this.orderLogPOs.isEmpty()) {
			return null;
		}

		for (PayOrderLogPO orderLogPO : this.orderLogPOs) {
			if (StringUtils.isNoneBlank(orderLogPO.getSerialNo())) {// 设置订单关闭状态
				return orderLogPO.getSerialNo();
			}
		}

		return null;
	}

	/**
	 * 查询对应步骤的成功记录
	 * 
	 * @author jiangmy
	 * @date 2017-04-18 11:44:03
	 * @since v1.0.0
	 * @param step
	 * @return
	 */
	public PayOrderLogPO getStepSuccess(PayStepEnum step) {
		if (this.orderLogPOs == null || this.orderLogPOs.isEmpty()) {
			return null;
		}

		for (PayOrderLogPO po : this.orderLogPOs) {
			if (step.isValue(po.getStep()) && PayRspCodeEnum.SUCCESS.isValue(po.getResultCode())) {
				return po;
			}
		}
		return null;
	}

	/**
	 * 取指定步骤的最新数据
	 * 
	 * @author buyi
	 * @date 2017-05-02 20:22:39
	 * @since v1.0.0
	 * @param step
	 * @return
	 */
	public PayOrderLogPO getStepLast(PayStepEnum step) {
		if (this.orderLogPOs == null || this.orderLogPOs.isEmpty()) {
			return null;
		}

		// 按照步骤降序，创建时间降序排序
		sortLogsByStepAndCreateTime(Ordering.natural().reverse(), Ordering.natural().reverse());

		for (PayOrderLogPO po : this.orderLogPOs) {
			if (step.isValue(po.getStep())) {
				return po;
			}
		}

		return null;
	}

	/**
	 * 获取支付结果步骤，包含：主动查询、异步通知
	 * 
	 * @author buyi
	 * @date 2017-05-02 20:24:33
	 * @since v1.0.0
	 *
	 * @return
	 */
	public PayOrderLogPO getResultLastStep() {
		if (null == orderLogPOs) {
			return null;
		}
		
		// 按照步骤降序，创建时间降序排序
		sortLogsByStepAndCreateTime(Ordering.natural().reverse(), Ordering.natural().reverse());

		for (PayOrderLogPO po : this.orderLogPOs) {
			if (PayStepEnum.STEP5_NOTIFY.isValue(po.getStep())) {
				continue;
			}
			
			if(PayStepEnum.STEP4_PAY_RESULT.isValue(po.getStep()) || PayStepEnum.STEP3_QUERY_RESULT.isValue(po.getStep())){
				return po;
			}
		}
		
		return null;
	}

	/**
	 * 支付日志排序
	 * 
	 * @author buyi
	 * @date 2017-05-02 10:32:13
	 * @since v1.0.0
	 * @param stepOrder
	 * @param createTimeOrder
	 */
	@SuppressWarnings("rawtypes")
	private void sortLogsByStepAndCreateTime(final Ordering stepOrder, final Ordering createTimeOrder) {
		if (this.orderLogPOs == null || this.orderLogPOs.isEmpty()) {
			return;
		}

		Collections.sort(this.orderLogPOs, new Comparator<PayOrderLogPO>() {
			@SuppressWarnings("unchecked")
			@Override
			public int compare(PayOrderLogPO object1, PayOrderLogPO object2) {
				return ComparisonChain.start().compare(object1.getStep(), object2.getStep(), stepOrder)
						.compare(object1.getCreateTime(), object2.getCreateTime(), createTimeOrder).result();
			}
		});
	}

}
